package com.coffeeloversupportlibrary.core.base;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author puyv
 * @createTime 2021/11/5 15:50
 * @projectName CoffeeLoverSupportLibrary
 * @className BaseFragment.java
 * @description TODO
 */
public abstract class BaseFragment<VM extends BaseViewModel,VDB extends ViewDataBinding> extends Fragment implements IView<VM>{

    private VM mViewModel;

    private VDB mBinding;

    private View mRootView;

    public VM getViewModel(){
        return this.mViewModel;
    }

    public VDB getBinding(){
        return this.mBinding;
    }

    public View getRootView(){
        return this.mRootView;
    }



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }



    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRootView = createRootView(inflater,container,savedInstanceState);
        if(isBinding()){
            mBinding = DataBindingUtil.bind(mRootView);
        }
        initViewModel();
        return mRootView;

    }

    private  View createRootView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){
        return inflater.inflate(getLayoutId(),container,false);
    }

    @Override
    public boolean isBinding() {
        return true;
    }

    /**
     * @date 2021/11/6 14:27
     * @params []
     * @return void
     * @description 数据发生改变时所驱动的 UI 变化,子类实现该方法
     */
    public abstract void registerUIChangeCallBack();



    /**
     * ===============================================================================
     */
    /**
    * @date 2021/11/5 16:12
    * @params []
    * @return void
    * @description 初始化 UI 的 ViewModel
    */
    private void initViewModel(){
        mViewModel = createViewModel();
        mViewModel.setModel();
        if(mViewModel != null){
            getLifecycle().addObserver(mViewModel);
            registerUIChangeCallBack();
        }
    }

    /**
     * @date 2021/11/5 15:08
     * @params []
     * @return VM
     * @description IView 接口方法的实现
     */
    @Override
    public VM createViewModel(){
        return obtainViewModel(getVMClass());
    }

    /**
     * @date 2021/11/5 15:10
     * @params []
     * @return java.lang.Class<VM>
     * @description 获取当前对象的 Class 对象
     */
    private Class<VM> getVMClass(){
        Class cls = getClass();
        Class<VM> vmClass = null;
        while (vmClass == null && cls!= null){
            vmClass = getVMClass(cls);
            cls = cls.getSuperclass();
        }
        if(vmClass == null){
            vmClass = (Class<VM>) BaseViewModel.class;
        }
        return vmClass;
    }

    /**
     * @date 2021/11/5 15:11
     * @params [cls]
     * @return java.lang.Class
     * @description 遍历当前 Class 对象的参数，找到 VM
     */
    private Class getVMClass(Class cls){
        Type type = cls.getGenericSuperclass();
        if(type instanceof ParameterizedType){
            Type[] types = ((ParameterizedType)type).getActualTypeArguments();
            for(Type t : types){
                if(t instanceof Class){
                    Class vmClass = (Class)t;
                    if(BaseViewModel.class.isAssignableFrom(vmClass)){
                        return vmClass;
                    }
                }else if(t instanceof ParameterizedType){
                    Type rawType = ((ParameterizedType)t).getRawType();
                    if(rawType instanceof Class){
                        Class vmClass = (Class)rawType;
                        if(BaseViewModel.class.isAssignableFrom(vmClass)){
                            return vmClass;
                        }
                    }
                }
            }
        }
        return null;
    }


    /**
     * @date 2021/11/5 15:15
     * @params [modelClass]
     * @return T
     * @description 通过  ViewModelProvider 获取相应的 ViewModel有则获取，无则创建
     */
    public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> modelClass){
        return new ViewModelProvider(this).get(modelClass);
    }
    /**
    * ===============================================================================
    */



    /**
    * @date 2021/11/5 16:16
    * @params [view, savedInstanceState]
    * @return void
    * @description 初始化数据交由子类完成
    */
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initData(savedInstanceState);
    }


    /**
     * ===============================================================================
     * 父类自动跟踪生命周期 处理资源的释放
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mViewModel != null){
            getLifecycle().removeObserver(mViewModel);
            mViewModel = null;
        }
        if(mBinding != null){
            mBinding.unbind();
        }
    }



    /**
     * =================================================================================
     */


    /**
    * @date 2021/11/6 15:01
    * @params [clz, bundle]
    * @return void
    * @description 启动 Activity 相关方法
    */
    protected void startActivity(Class<?> clz, Bundle bundle) {
        Intent intent = new Intent(this.getContext(), clz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    protected void startActivity(Class<?> clz) {
        startActivity(new Intent(this.getContext(), clz));
    }

    /**
    * @date 2021/11/6 15:02
    * @params
    * @return
    * @description 启动一个新的 Activity 并 Finish 之前的 Activity
    */
    protected void startActivityFinish(Class<?> clz, Bundle bundle){
        Intent intent = new Intent(this.getContext(), clz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        getActivity().finish();
    }

    protected void startActivityFinish(Class<?> clz){
        Intent intent = new Intent(this.getContext(), clz);
        startActivity(intent);
        getActivity().finish();
    }
    /**
     * =================================================================================
     */


}
